package com.example.redisdemo.aop;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.redisdemo.aop.annotation.AutoDoubleDelRedisData;
import com.example.redisdemo.utils.RedisUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * @ProjectName: redisdemo
 * @Package: com.example.redisdemo.aop
 * @ClassName: AutoDoubleDelRedisDataAspect
 * @Author: zlx
 * @Description:
 * @Date: 2022/6/18 11:41
 * @Version: 1.0
 */
@Aspect
@Component
public class AutoDoubleDelRedisDataAspect {
    //切入点
    @Pointcut("@annotation(com.example.redisdemo.aop.annotation.AutoDoubleDelRedisData)")
    public void doPointcut() {
    }

    /**
     * 环绕通知
     */
    @Around("doPointcut()")
    public Object doAroundAdvice(ProceedingJoinPoint point) throws Throwable {
        System.out.println("----------- 环绕通知 -----------");
        System.out.println("切入点目标方法名：" + point.getSignature().getName());
        //获取入参
        Object[] objs = point.getArgs();
        Object paramObject = null;
        if (objs.length > 0) {
            paramObject = objs[0];
        }
        //通过自定义注释获取自定义注解的方法对象
        MethodSignature methodSignature = (MethodSignature)point.getSignature();
        Method targetMethod = methodSignature.getMethod();//方法对象
        AutoDoubleDelRedisData annotation = targetMethod.getAnnotation(AutoDoubleDelRedisData.class);
        String[]  prefixs    = annotation.prefixs();
        String[] keyFields = annotation.keyFields();

        System.out.println("方法执行前：" + LocalDateTime.now());
        delRedisCache(paramObject,prefixs,keyFields);
        Object proceed = point.proceed();
        System.out.println("方法执行后：" + LocalDateTime.now());
        delRedisCache(paramObject,prefixs,keyFields);
        return proceed;
    }

    /**
     * 删除缓存信息
     * zlx
     * 16:29 2022/6/18
     * @param paramObject   入参参数
     * @param prefixs        键值前缀
     * @param keyFields     键值对饮id
     * @return void
     **/
    private void delRedisCache(Object paramObject,String[] prefixs,String[] keyFields) {
        for (int i = 0; i < prefixs.length; i++) {
            String redisKey = prefixs[i];
            String keyField = keyFields[i];
            if (paramObject.getClass() == String.class) {
                if (keyField != null && StrUtil.equals(keyField,"self")) {
                    redisKey = redisKey + paramObject;
                } else if (keyField != null && keyField.contains(";")) {
                    redisKey = buildRedisKey(redisKey,keyField,paramObject);
                }
            } else {
                if (StrUtil.isNotBlank(keyField)) {
                    redisKey = buildRedisKey(redisKey,keyField,paramObject);
                }
            }
            RedisUtils.scanDelKeys(redisKey);
        }

    }

    private String buildRedisKey(String redisKey, String keyField, Object paramObject) {
        String[] keys = keyField.split(";");
        for (int j = 0; j < keys.length; j++) {
            String key = keys[j];
            redisKey = redisKey + ReflectUtil.getFieldValue(paramObject, key);
            if (j == keys.length - 1) {
                redisKey = redisKey + "*";
            } else {
                redisKey = redisKey + ":";
            }
        }
        return redisKey;
    }
}
